﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ITAP.ShprossesBuilder.Modelling.Components;
using ITAP.ShprossesBuilder.Modelling;
using ITAP.ShprossesBuilder.Editor;
using ITAP.ShprossesBuilder.Calculations;
using ITAP.ShprossesBuilder.Properties;
using ITAP.Core.Modelling;
using ITAP.Core.Calculations;

namespace ITAP.ShprossesBuilder.Operations
{
    public class OperationMoveWithOffsetRelativeToComponentPosition : IOperation
    {
        private ModelControl modelControl;
        #region IOperation Members

        public string Name
        {
            get { return "Сместить относительно выбранного компонента"; }
        }

        public OperationGroup OperationGroup
        {
            get { return OperationGroup.Other; }
        }

        public System.Drawing.Image Thumbnail
        {
            get { return Resources.MoveWithOffsetRelativeToComponent.ToBitmap(); }
        }

        public void Execute(ModelControl modelControl)
        {
            this.modelControl = modelControl;

            if (modelControl.ModelContainer.SelectedComponentsStack.Count <= 1)
                return;

            ContextMenuStrip menuStrip = new ContextMenuStrip();

            EventHandler handler = new EventHandler(OnItemClick);
            ToolStripItem right = new ToolStripMenuItem("Вправо", null, handler);
            right.Tag = OffsetTo.Right;
            menuStrip.Items.Add(right);
            ToolStripItem up = new ToolStripMenuItem("Вверх", null, handler);
            up.Tag = OffsetTo.Up;
            menuStrip.Items.Add(up);
            ToolStripItem left = new ToolStripMenuItem("Влево", null, handler);
            left.Tag = OffsetTo.Left;
            menuStrip.Items.Add(left);
            ToolStripItem down = new ToolStripMenuItem("Вниз", null, handler);
            down.Tag = OffsetTo.Down;
            menuStrip.Items.Add(down);

            menuStrip.Show(Cursor.Position);
        }

        private void OnItemClick(object sender, EventArgs e)
        {
            ToolStripItem item = sender as ToolStripItem;
            OffsetTo offset = (OffsetTo)item.Tag;

            IComponent mainComponent = modelControl.ModelContainer.SelectedComponentsStack[0];

            MoveWithOffsetForm moveForm = new MoveWithOffsetForm("Смещение компонентов");

            if(moveForm.ShowDialog() != DialogResult.OK)
                return;

            ModelPoint mainPoint = null;
            if (mainComponent is ShprossConnector)
                mainPoint = mainComponent.Position;
            else if (mainComponent is Shpross)
                mainPoint = (mainComponent as Shpross).SelectedPointPosition;

            //ModelPoint moveToPoint = this.GetMoveToPoint(mainPoint, offset, moveForm.Offset);
            ModelPoint moveToPoint = null;

            for (int i = 1; i < modelControl.ModelContainer.SelectedComponentsStack.Count; i++)
            {
                IComponent component;
                IComponent selectedComponent = modelControl.ModelContainer.SelectedComponentsStack[i];
                if (moveForm.OffsetWithCopy)
                {
                    component = selectedComponent.Copy();
                    component.SerialNumber = 0;
                    selectedComponent.Parent.AddInnerComponent(component);
                }
                else
                    component = selectedComponent;

                if (component is ShprossConnector)
                {
                    moveToPoint = this.GetMoveToPoint(mainPoint, component.Position, offset, moveForm.Offset);
                    component.MoveTo(moveToPoint, component.Parent.BoundingBox);
                }
                else if (component is Shpross)
                {
                    Shpross shpross = component as Shpross;
                    if (shpross.SelectedPoint == ShprossPoints.Start)
                    {
                        moveToPoint = this.GetMoveToPoint(mainPoint, shpross.StartPoint, offset, moveForm.Offset);
                        shpross.MoveStartPointTo(moveToPoint, component.Parent.BoundingBox, false);
                    }
                    else if (shpross.SelectedPoint == ShprossPoints.End)
                    {
                        moveToPoint = this.GetMoveToPoint(mainPoint, shpross.EndPoint, offset, moveForm.Offset);
                        shpross.MoveEndPointTo(moveToPoint, component.Parent.BoundingBox, false);
                    }
                    else if (shpross.SelectedPoint == ShprossPoints.Center)
                    {
                        moveToPoint = this.GetMoveToPoint(mainPoint, shpross.Position, offset, moveForm.Offset);
                        shpross.MoveTo(moveToPoint, component.Parent.BoundingBox);
                    }
                }
            }

            modelControl.UpdateModel();
        }

        public bool CanUndo
        {
            get { return true; }
        }

        #endregion

        private ModelPoint GetMoveToPoint(ModelPoint source, ModelPoint componentPoint, OffsetTo offset, int offsetValue)
        {
            ModelVector vector = null;
            switch (offset)
            {
                case OffsetTo.Right:
                    vector = new ModelVector(offsetValue, 0);
                    break;
                case OffsetTo.Up:
                    vector = new ModelVector(0, offsetValue);
                    break;
                case OffsetTo.Left:
                    vector = new ModelVector(-offsetValue, 0);
                    break;
                case OffsetTo.Down:
                    vector = new ModelVector(0, -offsetValue);
                    break;
            }
            ModelPoint result = ModelCalculations.GetOffsetPoint(source, vector);
            if (offset == OffsetTo.Right || offset == OffsetTo.Left)
            {
                result.Y = componentPoint.Y;
            }
            else if (offset == OffsetTo.Up || offset == OffsetTo.Down)
            {
                result.X = componentPoint.X;
            }
            return result;
        }

    }
}
